﻿using System;
using System.Diagnostics;
using System.IO;
using System.IO.Packaging;
using System.Linq;

namespace Microsoft.Isam.Esent.Serialization
{
	partial class SerializerSession : iSerializerSessionImpl
	{
		#region Single table import / export
		public void /* iSerializerSession. */ ImportTable( Type tRecord, Stream stm, ImportExportFormat fmt )
		{
			ImportExportImpl( true, tRecord, stm, fmt );
		}

		public void /* iSerializerSession. */ ExportTable( Type tRecord, Stream stm, ImportExportFormat fmt )
		{
			ImportExportImpl( false, tRecord, stm, fmt );
		}

		void ImportExportImpl( bool bImporting, Type tRecord, Stream stm, ImportExportFormat fmt )
		{
			sTable tbl;
			if( !m_tables.TryGetValue( tRecord, out tbl ) )
				throw new ArgumentException( "Table with records of type '" + tRecord.Name + "' doesn't exist in this session." );

			ImportExport ie = null;
			if( fmt == ImportExportFormat.TSV )
				ie = new ImportExportTSV( this, tbl.idTable, tbl.serializer );
			else if( fmt == ImportExportFormat.Binary )
				ie = new ImportExportBinary( this, tbl.idTable, tbl.serializer );
			else
				throw new NotSupportedException( "The ImportExportFormat is not supported." );

			if( bImporting )
			{
				ClearTable( tbl.idTable );
				ie.Import( stm );
			}
			else
				ie.Export( stm );
		}
		#endregion

		#region Pack many tables into single .ZIP

		public void ExportTables( Type[] tRecords, string exportFile )
		{
			if( File.Exists( exportFile ) )
				File.Delete( exportFile );

			tRecords.ForEach( t => this.AddType( t ) );

			using( var trans = BeginTransaction() )
			using( Package zip = Package.Open( exportFile, FileMode.Create ) )
				tRecords.ForEach( tp => ExportTable( zip, tp ) );
		}

		/// <summary>Export table, writing it into the TSV file inside the ZIP package.</summary>
		/// <param name="zip">ZIP package</param>
		/// <param name="tp">Records type to serialize</param>
		void ExportTable( Package zip, Type tp )
		{
			string strFileName = m_tables[ tp ].serializer.tableName + ".tsv";

			string destFilename = ".\\" + strFileName;
			Uri uri = PackUriHelper.CreatePartUri( new Uri( destFilename, UriKind.Relative ) );
			PackagePart part = zip.CreatePart( uri, "", CompressionOption.Maximum );
			ExportTable( tp, part.GetStream(), Microsoft.Isam.Esent.Serialization.ImportExportFormat.TSV );
		}

		public void ImportTables( string importFile )
		{
			using( Package zip = Package.Open( importFile, FileMode.Open ) )
			{
				foreach( PackagePart part in zip.GetParts() )
				{
					// Mess with the file name
					string fn = part.Uri.ToString().ToLowerInvariant();
					if( !fn.EndsWith( ".tsv" ) )
						continue;
					fn.Replace( '\\', '/' );
					if( fn.Contains( "/" ) )
						fn = fn.Substring( fn.LastIndexOf( '/' ) + 1 );
					fn = fn.Substring( 0, fn.Length - 4 );

					// Find the type
					Type tp = GetAllTypes().First( p => p.second.ToLowerInvariant() == fn ).first;

					// Import the table
					ImportTable( tp, part.GetStream( FileMode.Open, FileAccess.Read ), ImportExportFormat.TSV );
				}
			}
		}
		#endregion
	}
}